/*!	 blineconvert.h
**	 Template Header
**
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
**
**	This package is free software; you can redistribute it and/or
**	modify it under the terms of the GNU General Public License as
**	published by the Free Software Foundation; either version 2 of
**	the License, or (at your option) any later version.
**
**	This package is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**	General Public License for more details.
**
*/

#ifndef __SYNFIG_BLINE_CONVERT_H
#define __SYNFIG_BLINE_CONVERT_H

#include <synfig/blinepoint.h>
#include <list>
#include <vector>

namespace synfigapp
{

class BLineConverter
{
public:
    struct cpindex {
        int 		curind;
        synfig::Real	tangentscale;
        synfig::Real	error;	// negative error will indicate invalid;

        cpindex(int ci, synfig::Real s = 0, synfig::Real e = -1)
            : curind(ci), tangentscale(s), error(e)
        {}

        cpindex(const cpindex & o)
            : curind(o.curind), tangentscale(o.tangentscale), error(o.error)
        {}

        const cpindex & operator=(const cpindex & rhs)
        {
            curind = rhs.curind;
            tangentscale = rhs.tangentscale;
            error = rhs.error;
            return *this;
        }

        bool operator<(const cpindex &rhs) const
        {
            return curind < rhs.curind;
        }

        // point is obviously in[curind]
        // tangent scale will get reset to the smallest (or something else depending on experimentation)
    };

private:
    // cached data
    std::vector<synfig::Point>	point_cache;	// the preprocessed input cache
    std::vector<synfig::Real>	width_cache;

    // temporary point storage for vector calc
    std::vector<synfig::Point>	ftemp;

    std::vector<synfig::Vector>	deriv; // the derivative cache
    std::vector<synfig::Real>	curvature; // the curvature cache

    std::vector<int>			break_tangents; // the break point cache

    std::vector<synfig::Real> 	cum_dist,	// cumulative distance
         this_dist; // distance between adjacent segments

    std::vector<synfig::Point>	work; // the working point cache for the entire curve
    std::vector<cpindex> 		curind;

    // function parameters
    void clear();

public:
    synfig::Real width;

    // Converter properties
    synfig::Real pixelwidth;
    synfig::Real smoothness; // actual error will be smoothness*pixelwidth (for global set pixelwidth = 1)

    BLineConverter();

    static void EnforceMinWidth(std::list<synfig::BLinePoint> &bline, synfig::Real min_pressure);
    void operator()(std::list<synfig::BLinePoint> &out, const std::list<synfig::Point> &in, const std::list<synfig::Real> &in_w);
};

}; // END of namespace synfigapp

#endif